package com.ofhb.webapp.client.forms;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.ofhb.webapp.client.utils.AppClientUtils;
import com.ofhb.webapp.client.utils.DataCache;
import com.ofhb.webapp.client.utils.RegEx;
import com.ofhb.webapp.client.utils.ServiceUtil;
import com.ofhb.webapp.shared.dto.CityDTO;
import com.ofhb.webapp.shared.dto.UserDTO;
import com.ofhb.webapp.shared.dto.UserTypeDTO;

public class UserForm extends FlexTable {

	private TextBox textBoxPrimaryPhone;
	private TextBox textBoxPinCode;
	private TextBox textBoxAddressLine2;
	private TextBox textBoxAddressLine1;
	private TextBox textBoxPrimaryEmail;
	private ListBox comboBoxDateOfBirthMonth;
	private ListBox comboBoxDateOfBirthDay;
	private TextBox textBoxFirstName;
	private TextBox textBoxSecondaryPhone;
	private TextBox textBoxMiddleName;
	private ListBox comboBoxDateOfBirthYear;
	private TextBox textBoxLastName;
	private TextBox textBoxSecondaryEmail;
	private PasswordTextBox passwordBoxConfirmPassword;
	private TextBox textBoxUserName;
	private ListBox listBoxUserType;
	private TextBox textBoxSecurityAnswer;
	private ListBox listBoxSecurityQuestion;
	private PasswordTextBox passwordBoxPassword;
	private TextBox textBoxHintForSecurityAnswer;

	private FlexTable ftErrorSecurityQuestion;
	private FlexTable ftErrorDateOfBirth;
	private FlexTable ftErrorUserType;

	private ArrayList<FocusWidget> formValidationWidgets;

	private HashMap<String, UserTypeDTO> mapUserTypes = new HashMap<String, UserTypeDTO>();
	private Button btnSubmit;
	private Button btnReset;
	private SuggestBox suggestBoxCityState;

	public UserForm() {
		
		setSize("100%", "");

		VerticalPanel vpPersonalInformation = new VerticalPanel();
		vpPersonalInformation.setStyleName("ofhb-form-section");
		setWidget(0, 0, vpPersonalInformation);
		vpPersonalInformation.setWidth("100%");

		Label lblPersonalInformation = new Label("Personal Information");
		vpPersonalInformation.add(lblPersonalInformation);
		lblPersonalInformation.setStyleName("ofhb-form-section-header-lbl");

		FlexTable ftFormPersonalInformation = new FlexTable();
		ftFormPersonalInformation.setCellSpacing(5);
		vpPersonalInformation.add(ftFormPersonalInformation);

		Label lblFirstName = new Label("* First Name :");
		lblFirstName.setStyleName("ofhb-form-field-required-lbl");
		ftFormPersonalInformation.setWidget(0, 0, lblFirstName);
		lblFirstName.setWidth("175px");

		FlexTable ftFirstName = new FlexTable();
		ftFormPersonalInformation.setWidget(0, 1, ftFirstName);

		textBoxFirstName = new TextBox();
		textBoxFirstName.setMaxLength(64);
		ftFirstName.setWidget(0, 0, textBoxFirstName);
		textBoxFirstName.setVisibleLength(32);

		textBoxFirstName.getElement().setAttribute("required", "true");
		textBoxFirstName.getElement().setAttribute("regEx", RegEx.NAME);
		textBoxFirstName
				.getElement()
				.setPropertyObject(
						"errorBox",
						AppClientUtils
								.getFieldErrorBox("Please enter valid first name only charaters allowed. Min 2 and max 64 characters"));

		Label lblMiddleName = new Label("Middle Name :");
		lblMiddleName.setStyleName("ofhb-form-field-lbl");
		ftFormPersonalInformation.setWidget(1, 0, lblMiddleName);
		lblMiddleName.setWidth("175px");

		FlexTable ftMiddleName = new FlexTable();
		ftFormPersonalInformation.setWidget(1, 1, ftMiddleName);

		textBoxMiddleName = new TextBox();
		textBoxMiddleName.setMaxLength(64);
		textBoxMiddleName.setVisibleLength(32);
		ftMiddleName.setWidget(0, 0, textBoxMiddleName);

		textBoxMiddleName.getElement().setAttribute("required", "false");
		textBoxMiddleName.getElement().setAttribute("regEx", RegEx.NAME);
		textBoxMiddleName.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid middle name only charaters allowed"));

		Label lblLastName = new Label("* Last Name :");
		lblLastName.setStyleName("ofhb-form-field-required-lbl");
		ftFormPersonalInformation.setWidget(2, 0, lblLastName);
		lblLastName.setWidth("175px");

		FlexTable ftLastName = new FlexTable();
		ftFormPersonalInformation.setWidget(2, 1, ftLastName);

		textBoxLastName = new TextBox();
		textBoxLastName.setMaxLength(64);
		textBoxLastName.setVisibleLength(32);
		ftLastName.setWidget(0, 0, textBoxLastName);

		textBoxLastName.getElement().setAttribute("required", "true");
		textBoxLastName.getElement().setAttribute("regEx", RegEx.NAME);
		textBoxLastName.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid last name only charaters allowed"));

		Label lblDateOfBirth = new Label("* Date of Birth :");
		lblDateOfBirth.setStyleName("ofhb-form-field-required-lbl");
		ftFormPersonalInformation.setWidget(3, 0, lblDateOfBirth);
		lblDateOfBirth.setWidth("175px");

		FlexTable ftDateOfBirth = new FlexTable();
		ftFormPersonalInformation.setWidget(3, 1, ftDateOfBirth);

		comboBoxDateOfBirthDay = new ListBox();
		comboBoxDateOfBirthDay.setVisibleItemCount(1);
		ftDateOfBirth.setWidget(0, 0, comboBoxDateOfBirthDay);
		comboBoxDateOfBirthDay.setWidth("75px");
		comboBoxDateOfBirthDay.addItem("-");
		for (int i = 1; i <= 31; i++) {
			comboBoxDateOfBirthDay.addItem(String.valueOf(i), String.valueOf(i));
		}

		comboBoxDateOfBirthMonth = new ListBox();
		ftDateOfBirth.setWidget(0, 1, comboBoxDateOfBirthMonth);
		comboBoxDateOfBirthMonth.setWidth("75px");
		comboBoxDateOfBirthMonth.addItem("-");
		for (int i = 1; i <= 12; i++) {
			comboBoxDateOfBirthMonth.addItem(String.valueOf(i), String.valueOf(i));
		}
		comboBoxDateOfBirthMonth.setSelectedIndex(-1);

		comboBoxDateOfBirthYear = new ListBox();
		ftDateOfBirth.setWidget(0, 2, comboBoxDateOfBirthYear);
		comboBoxDateOfBirthYear.setWidth("75px");
		comboBoxDateOfBirthYear.addItem("-");
		@SuppressWarnings("deprecation")
		int year = new Date().getYear();
		year = 1900 + year - 18;

		for (int i = 1900; i <= year; i++) {
			comboBoxDateOfBirthYear.addItem(String.valueOf(i), String.valueOf(i));
		}

		ftErrorDateOfBirth = new FlexTable();
		ftErrorDateOfBirth.setStyleName("ofhb-form-field-error-table");
		ftDateOfBirth.setWidget(0, 3, ftErrorDateOfBirth);
		ftErrorDateOfBirth.setVisible(false);

		Image image_2 = new Image("resources/images/field_error.png");
		ftErrorDateOfBirth.setWidget(0, 0, image_2);
		image_2.setSize("16px", "16px");

		Label lblPleaseEnterValid_2 = new Label("Please enter valid date of birth");
		ftErrorDateOfBirth.setWidget(0, 1, lblPleaseEnterValid_2);

		comboBoxDateOfBirthDay.getElement().setPropertyObject("errorBox", ftErrorDateOfBirth);
		comboBoxDateOfBirthMonth.getElement().setPropertyObject("errorBox", ftErrorDateOfBirth);
		comboBoxDateOfBirthYear.getElement().setPropertyObject("errorBox", ftErrorDateOfBirth);

		ftFormPersonalInformation.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormPersonalInformation.getCellFormatter().setHorizontalAlignment(1, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormPersonalInformation.getCellFormatter().setHorizontalAlignment(2, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormPersonalInformation.getCellFormatter().setHorizontalAlignment(3, 0, HasHorizontalAlignment.ALIGN_RIGHT);

		VerticalPanel vpContactInformation = new VerticalPanel();
		vpContactInformation.setStyleName("ofhb-form-section");
		setWidget(2, 0, vpContactInformation);
		vpContactInformation.setWidth("100%");

		Label lblContactInformation = new Label("Contact Information");
		lblContactInformation.setStyleName("ofhb-form-section-header-lbl");
		vpContactInformation.add(lblContactInformation);

		FlexTable ftFormContactInformation = new FlexTable();
		ftFormContactInformation.setCellSpacing(5);
		vpContactInformation.add(ftFormContactInformation);
		ftFormContactInformation.setSize("", "");

		Label lblAddressLine1 = new Label("* Address Line 1 :");
		lblAddressLine1.setStyleName("ofhb-form-field-required-lbl");
		ftFormContactInformation.setWidget(0, 0, lblAddressLine1);
		lblAddressLine1.setWidth("175px");

		FlexTable ftAddressLine1 = new FlexTable();
		ftFormContactInformation.setWidget(0, 1, ftAddressLine1);

		textBoxAddressLine1 = new TextBox();
		textBoxAddressLine1.setMaxLength(128);
		textBoxAddressLine1.setVisibleLength(50);
		ftAddressLine1.setWidget(0, 0, textBoxAddressLine1);

		textBoxAddressLine1.getElement().setAttribute("required", "true");
		textBoxAddressLine1.getElement().setAttribute("regEx", RegEx.ADDRESS);
		textBoxAddressLine1.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid Address Line 1 (No Special Charaters)"));

		Label lblAddressLine2 = new Label("Address Line 2 :");
		lblAddressLine2.setStyleName("ofhb-form-field-lbl");
		ftFormContactInformation.setWidget(1, 0, lblAddressLine2);
		lblAddressLine2.setWidth("175px");

		FlexTable ftAddressLine2 = new FlexTable();
		ftFormContactInformation.setWidget(1, 1, ftAddressLine2);

		textBoxAddressLine2 = new TextBox();
		textBoxAddressLine2.setMaxLength(128);
		textBoxAddressLine2.setVisibleLength(50);
		ftAddressLine2.setWidget(0, 0, textBoxAddressLine2);

		textBoxAddressLine2.getElement().setAttribute("required", "false");
		textBoxAddressLine2.getElement().setAttribute("regEx", RegEx.ADDRESS);
		textBoxAddressLine2.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid Address Line 2 (No Special Charaters)"));
		
		Label lblCity = new Label("* City :");
		lblCity.setStyleName("ofhb-form-field-required-lbl");
		ftFormContactInformation.setWidget(2, 0, lblCity);
		lblCity.setWidth("175px");
		
		suggestBoxCityState = new SuggestBox(DataCache.getCityOracle());
		suggestBoxCityState.setWidth("200px");

		FlexTable ftCity = new FlexTable();
		ftFormContactInformation.setWidget(2, 1, ftCity);
		
		suggestBoxCityState.getElement().setAttribute("required", "true");
		suggestBoxCityState.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid City (No Special Charaters)"));
		ftCity.setWidget(0, 0, suggestBoxCityState);


		Label lblPinCode = new Label("* Pin Code :");
		lblPinCode.setStyleName("ofhb-form-field-required-lbl");
		ftFormContactInformation.setWidget(3, 0, lblPinCode);
		lblPinCode.setWidth("175px");

		FlexTable ftPinCode = new FlexTable();
		ftFormContactInformation.setWidget(3, 1, ftPinCode);

		textBoxPinCode = new TextBox();
		textBoxPinCode.setMaxLength(6);
		textBoxPinCode.setVisibleLength(6);
		ftPinCode.setWidget(0, 0, textBoxPinCode);

		textBoxPinCode.getElement().setAttribute("required", "true");
		textBoxPinCode.getElement().setAttribute("regEx", RegEx.PIN_CODE);
		textBoxPinCode.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter 6 digit pin code number"));

		Label lblPrimaryPhone = new Label("* Primary Phone :");
		lblPrimaryPhone.setStyleName("ofhb-form-field-required-lbl");
		ftFormContactInformation.setWidget(4, 0, lblPrimaryPhone);
		lblPrimaryPhone.setWidth("175px");

		FlexTable ftPrimaryPhone = new FlexTable();
		ftFormContactInformation.setWidget(4, 1, ftPrimaryPhone);

		textBoxPrimaryPhone = new TextBox();
		textBoxPrimaryPhone.setMaxLength(10);
		textBoxPrimaryPhone.setVisibleLength(10);
		ftPrimaryPhone.setWidget(0, 0, textBoxPrimaryPhone);

		textBoxPrimaryPhone.getElement().setAttribute("required", "true");
		textBoxPrimaryPhone.getElement().setAttribute("regEx", RegEx.MOBILE_NUMBER);
		textBoxPrimaryPhone
				.getElement()
				.setPropertyObject(
						"errorBox",
						AppClientUtils
								.getFieldErrorBox("Please enter valid primary mobile phone number (Notification can be send through SMS)"));

		Label lblSecondaryPhone = new Label("Secondary Phone :");
		lblSecondaryPhone.setStyleName("ofhb-form-field-lbl");
		ftFormContactInformation.setWidget(5, 0, lblSecondaryPhone);
		lblSecondaryPhone.setWidth("175px");

		FlexTable ftSecondaryPhone = new FlexTable();
		ftFormContactInformation.setWidget(5, 1, ftSecondaryPhone);

		textBoxSecondaryPhone = new TextBox();
		textBoxSecondaryPhone.setMaxLength(10);
		textBoxSecondaryPhone.setVisibleLength(10);
		ftSecondaryPhone.setWidget(0, 0, textBoxSecondaryPhone);

		textBoxSecondaryPhone.getElement().setAttribute("required", "false");
		textBoxSecondaryPhone.getElement().setAttribute("regEx", RegEx.MOBILE_NUMBER);
		textBoxSecondaryPhone
				.getElement()
				.setPropertyObject(
						"errorBox",
						AppClientUtils
								.getFieldErrorBox("Please enter valid secondary mobile phone number, used when primary not available"));

		Label lblPrimaryEmail = new Label("* Primary Email :");
		lblPrimaryEmail.setStyleName("ofhb-form-field-required-lbl");
		ftFormContactInformation.setWidget(6, 0, lblPrimaryEmail);
		lblPrimaryEmail.setWidth("175px");

		FlexTable ftPrimaryEmail = new FlexTable();
		ftFormContactInformation.setWidget(6, 1, ftPrimaryEmail);

		textBoxPrimaryEmail = new TextBox();
		textBoxPrimaryEmail.setMaxLength(128);
		textBoxPrimaryEmail.setVisibleLength(50);
		ftPrimaryEmail.setWidget(0, 0, textBoxPrimaryEmail);

		textBoxPrimaryEmail.getElement().setAttribute("required", "true");
		textBoxPrimaryEmail.getElement().setAttribute("regEx", RegEx.EMAIL);
		textBoxPrimaryEmail
				.getElement()
				.setPropertyObject(
						"errorBox",
						AppClientUtils
								.getFieldErrorBox("Please enter valid primary email address, used to send notifications and recovery of user name and password"));

		Label lblSecondaryEmail = new Label("Secondary Email :");
		lblSecondaryEmail.setStyleName("ofhb-form-field-lbl");
		ftFormContactInformation.setWidget(7, 0, lblSecondaryEmail);
		lblSecondaryEmail.setWidth("175px");

		FlexTable ftSecondaryEmail = new FlexTable();
		ftFormContactInformation.setWidget(7, 1, ftSecondaryEmail);

		textBoxSecondaryEmail = new TextBox();
		textBoxSecondaryEmail.setMaxLength(128);
		textBoxSecondaryEmail.setVisibleLength(50);
		ftSecondaryEmail.setWidget(0, 0, textBoxSecondaryEmail);

		textBoxSecondaryEmail.getElement().setAttribute("required", "false");
		textBoxSecondaryEmail.getElement().setAttribute("regEx", RegEx.EMAIL);
		textBoxSecondaryEmail
				.getElement()
				.setPropertyObject(
						"errorBox",
						AppClientUtils
								.getFieldErrorBox("Please enter valid secondary email address, used when primary is not available"));

		ftFormContactInformation.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormContactInformation.getCellFormatter().setHorizontalAlignment(1, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormContactInformation.getCellFormatter().setHorizontalAlignment(2, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormContactInformation.getCellFormatter().setHorizontalAlignment(3, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormContactInformation.getCellFormatter().setHorizontalAlignment(4, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormContactInformation.getCellFormatter().setHorizontalAlignment(5, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormContactInformation.getCellFormatter().setHorizontalAlignment(6, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormContactInformation.getCellFormatter().setHorizontalAlignment(7, 0, HasHorizontalAlignment.ALIGN_RIGHT);

		VerticalPanel vpAccountInformation = new VerticalPanel();
		vpAccountInformation.setStyleName("ofhb-form-section");
		setWidget(4, 0, vpAccountInformation);
		vpAccountInformation.setWidth("100%");

		Label lblAccountInformation = new Label("Account Information");
		lblAccountInformation.setStyleName("ofhb-form-section-header-lbl");
		vpAccountInformation.add(lblAccountInformation);

		FlexTable ftFormAccountInformation = new FlexTable();
		ftFormAccountInformation.setCellSpacing(5);
		vpAccountInformation.add(ftFormAccountInformation);
		ftFormAccountInformation.setSize("", "");

		Label lblUserType = new Label("* User Type :");
		lblUserType.setStyleName("ofhb-form-field-required-lbl");
		lblUserType.setWordWrap(false);
		ftFormAccountInformation.setWidget(0, 0, lblUserType);
		lblUserType.setWidth("175px");

		FlexTable ftUserType = new FlexTable();
		ftFormAccountInformation.setWidget(0, 1, ftUserType);

		listBoxUserType = new ListBox();
		ftUserType.setWidget(0, 0, listBoxUserType);
		listBoxUserType.addItem("-Select user type-");
		AsyncCallback<List<UserTypeDTO>> callback = new AsyncCallback<List<UserTypeDTO>>() {

			@Override
			public void onSuccess(List<UserTypeDTO> result) {
				mapUserTypes.clear();
				for (UserTypeDTO userTypeDTO : result) {
					listBoxUserType.addItem(userTypeDTO.getDisplayName(), String.valueOf(userTypeDTO.getId()));
					mapUserTypes.put(String.valueOf(userTypeDTO.getId()), userTypeDTO);
					
				}
				enterFakeData();
				btnSubmit.setEnabled(true);
			}

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("onFailure : " + caught.getMessage());
			}
		};
		ServiceUtil.DATA_READER_SERVICE.getUserTypes(callback);

		ftErrorUserType = new FlexTable();
		ftErrorUserType.setStyleName("ofhb-form-field-error-table");
		ftUserType.setWidget(0, 1, ftErrorUserType);
		ftErrorUserType.setVisible(false);

		Image image_17 = new Image("resources/images/field_error.png");
		ftErrorUserType.setWidget(0, 0, image_17);
		image_17.setSize("16px", "16px");

		Label lblPleaseSelectCorrect = new Label("Please select correct user type");
		lblPleaseSelectCorrect.setWordWrap(false);
		ftErrorUserType.setWidget(0, 1, lblPleaseSelectCorrect);

		listBoxUserType.getElement().setPropertyObject("errorBox", ftErrorUserType);

		Label lblUserName = new Label("* User Name :");
		lblUserName.setStyleName("ofhb-form-field-required-lbl");
		lblUserName.setWordWrap(false);
		ftFormAccountInformation.setWidget(1, 0, lblUserName);
		lblUserName.setWidth("175px");

		FlexTable ftUserName = new FlexTable();
		ftFormAccountInformation.setWidget(1, 1, ftUserName);

		textBoxUserName = new TextBox();
		textBoxUserName.setVisibleLength(35);
		ftUserName.setWidget(0, 0, textBoxUserName);

		textBoxUserName.getElement().setAttribute("required", "true");
		textBoxUserName.getElement().setAttribute("regEx", RegEx.USER_NAME);
		textBoxUserName.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid user name (Alphanumeric only)"));
		
		textBoxUserName.getElement().setPropertyObject("duplicateUserName",
				AppClientUtils.getFieldErrorBox("Entered username is already taken. Please enter different valid user name"));

		Label lblPassword = new Label("* Password :");
		lblPassword.setStyleName("ofhb-form-field-required-lbl");
		lblPassword.setWordWrap(false);
		ftFormAccountInformation.setWidget(2, 0, lblPassword);
		lblPassword.setWidth("175px");

		FlexTable ftPassword = new FlexTable();
		ftFormAccountInformation.setWidget(2, 1, ftPassword);

		passwordBoxPassword = new PasswordTextBox();
		ftPassword.setWidget(0, 0, passwordBoxPassword);

		passwordBoxPassword.getElement().setAttribute("required", "true");
		passwordBoxPassword.getElement().setAttribute("regEx", RegEx.PASSWORD);
		passwordBoxPassword.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid password (Use characters, number, min 6 length)"));

		Label lblConfirmPassword = new Label("* Confirm Password :");
		lblConfirmPassword.setStyleName("ofhb-form-field-required-lbl");
		lblConfirmPassword.setWordWrap(false);
		ftFormAccountInformation.setWidget(3, 0, lblConfirmPassword);
		lblConfirmPassword.setWidth("175px");

		FlexTable ftConfirmPassword = new FlexTable();
		ftFormAccountInformation.setWidget(3, 1, ftConfirmPassword);

		passwordBoxConfirmPassword = new PasswordTextBox();
		ftConfirmPassword.setWidget(0, 0, passwordBoxConfirmPassword);
		passwordBoxConfirmPassword.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Confirm password is not matching with password"));
		passwordBoxConfirmPassword.getElement().setId("passwordTextBoxConfirmPassword");

		Label lblSecurityQuestion = new Label("* Security Question :");
		lblSecurityQuestion.setStyleName("ofhb-form-field-required-lbl");
		lblSecurityQuestion.setWordWrap(false);
		ftFormAccountInformation.setWidget(4, 0, lblSecurityQuestion);
		lblSecurityQuestion.setWidth("175px");

		FlexTable ftSecurityQuestion = new FlexTable();
		ftFormAccountInformation.setWidget(4, 1, ftSecurityQuestion);

		listBoxSecurityQuestion = AppClientUtils.getSecurityQuestionsListBox();
		ftSecurityQuestion.setWidget(0, 0, listBoxSecurityQuestion);

		ftErrorSecurityQuestion = new FlexTable();
		ftErrorSecurityQuestion.setStyleName("ofhb-form-field-error-table");
		ftSecurityQuestion.setWidget(0, 1, ftErrorSecurityQuestion);
		ftErrorSecurityQuestion.setVisible(false);

		Image image_18 = new Image("resources/images/field_error.png");
		ftErrorSecurityQuestion.setWidget(0, 0, image_18);
		image_18.setSize("16px", "16px");

		Label lblPleaseSelectSecurity = new Label("Please select security question");
		lblPleaseSelectSecurity.setWordWrap(false);
		ftErrorSecurityQuestion.setWidget(0, 1, lblPleaseSelectSecurity);

		listBoxSecurityQuestion.getElement().setPropertyObject("errorBox", ftErrorSecurityQuestion);

		Label lblSecurityAnswer = new Label("* Security Answer :");
		lblSecurityAnswer.setStyleName("ofhb-form-field-required-lbl");
		lblSecurityAnswer.setWordWrap(false);
		ftFormAccountInformation.setWidget(5, 0, lblSecurityAnswer);
		lblSecurityAnswer.setWidth("175px");

		FlexTable ftSecurityAnswer = new FlexTable();
		ftFormAccountInformation.setWidget(5, 1, ftSecurityAnswer);

		textBoxSecurityAnswer = new TextBox();
		textBoxSecurityAnswer.setVisibleLength(35);
		ftSecurityAnswer.setWidget(0, 0, textBoxSecurityAnswer);
		textBoxSecurityAnswer.getElement().setAttribute("required", "true");
		textBoxSecurityAnswer.getElement().setAttribute("regEx", RegEx.USER_NAME);
		textBoxSecurityAnswer.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid user name (Alphanumeric only)"));

		ftFormAccountInformation.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormAccountInformation.getCellFormatter().setHorizontalAlignment(1, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormAccountInformation.getCellFormatter().setHorizontalAlignment(2, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormAccountInformation.getCellFormatter().setHorizontalAlignment(3, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormAccountInformation.getCellFormatter().setHorizontalAlignment(4, 0, HasHorizontalAlignment.ALIGN_RIGHT);
		ftFormAccountInformation.getCellFormatter().setHorizontalAlignment(5, 0, HasHorizontalAlignment.ALIGN_RIGHT);

		Label lblHintForSecurityAnswer = new Label("* Hint for Security Answer");
		lblHintForSecurityAnswer.setStyleName("ofhb-form-field-required-lbl");
		ftFormAccountInformation.setWidget(6, 0, lblHintForSecurityAnswer);
		ftFormAccountInformation.getCellFormatter().setHorizontalAlignment(6, 0, HasHorizontalAlignment.ALIGN_RIGHT);

		FlexTable ftHintForSecurityAnswer = new FlexTable();
		ftFormAccountInformation.setWidget(6, 1, ftHintForSecurityAnswer);

		textBoxHintForSecurityAnswer = new TextBox();
		textBoxHintForSecurityAnswer.setMaxLength(64);
		textBoxHintForSecurityAnswer.setVisibleLength(32);
		ftHintForSecurityAnswer.setWidget(0, 0, textBoxHintForSecurityAnswer);
		textBoxHintForSecurityAnswer.getElement().setAttribute("required", "true");
		textBoxHintForSecurityAnswer.getElement().setAttribute("regEx", RegEx.SECURITY_ANSWER);
		textBoxHintForSecurityAnswer.getElement().setPropertyObject("errorBox",
				AppClientUtils.getFieldErrorBox("Please enter valid Hint For Security Answer (Alphanumeric only)"));

		FlexTable ftButtonPanel = new FlexTable();
		ftButtonPanel.setCellSpacing(5);
		setWidget(5, 0, ftButtonPanel);
		getCellFormatter().setStyleName(5, 0, "ofhb-form-section-header-lbl");
		ftButtonPanel.setWidth("");

		btnSubmit = new Button();
		btnSubmit.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (isFormValid()) {
					checkForDuplicateUserNameAndSubmit(textBoxUserName.getText().trim());
				}
			}
		});
		btnSubmit.setText("Submit");
		ftButtonPanel.setWidget(0, 0, btnSubmit);
		btnSubmit.setWidth("100px");
		btnSubmit.setEnabled(false);

		btnReset = new Button();
		btnReset.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				reset();
			}
		});
		btnReset.setText("Reset");
		ftButtonPanel.setWidget(0, 1, btnReset);
		btnReset.setWidth("100px");
		getCellFormatter().setHorizontalAlignment(5, 0, HasHorizontalAlignment.ALIGN_CENTER);

	}

	private void checkForDuplicateUserNameAndSubmit(String userName){
		
		AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
			
			@Override
			public void onSuccess(Boolean result) {
				if(!result) {
					clearDuplicateUserNameError(textBoxUserName);
					submit();
				} else {
					setDuplicateUserNameErrorFor(textBoxUserName);
				}
			}
			
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("onFailure : " + caught.getLocalizedMessage());
			}
		};
		ServiceUtil.DATA_READER_SERVICE.isUserNameExists(userName, callback);
	}
	
	private void submit() {
		UserDTO userDTO = getUserDTO();
		AsyncCallback<UserDTO> callback = new AsyncCallback<UserDTO>() {

			@Override
			public void onSuccess(UserDTO result) {
				if(result != null) {
					Window.alert("Success : " + result.getId());
					reset();
				}
			}

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("onFailure : " + caught.getMessage());

			}
		};
		ServiceUtil.DATA_WRITER_SERVICE.save(userDTO, callback);
	}

	private void reset() {
		int size = getFormValidationWidgets().size();
		for (int i = size - 1; i >= 0; i--) {
			FocusWidget temp = getFormValidationWidgets().get(i);
			if (temp.getClass().toString().contains("ListBox")) {
				ListBox tempListBox = (ListBox) temp;
				tempListBox.setSelectedIndex(0);
				clearError(tempListBox);
			} else if (temp.getClass().toString().contains("TextBox")) {
				TextBox tempTextBox = (TextBox) temp;
				tempTextBox.setText("");
				clearError(tempTextBox);
			}
		}
		clearError(suggestBoxCityState);
		suggestBoxCityState.getTextBox().setText("");
	}

	private boolean isFormValid() {
		boolean result = true;
		
		if (isSuggestBoxValid(suggestBoxCityState)) {
			clearError(suggestBoxCityState);
		} else {
			setErrorFor(suggestBoxCityState);
			suggestBoxCityState.setFocus(true);
			result = false;
		}


		int size = getFormValidationWidgets().size();
		for (int i = size - 1; i >= 0; i--) {
			FocusWidget temp = getFormValidationWidgets().get(i);

			if (temp.getElement().getId().equalsIgnoreCase("passwordTextBoxConfirmPassword")) {
				if (!passwordBoxConfirmPassword.getText().trim().equals(passwordBoxPassword.getText().trim())) {
					result = false;
					setErrorFor(passwordBoxConfirmPassword);
					passwordBoxConfirmPassword.setFocus(true);
				} else {
					clearError(passwordBoxConfirmPassword);
				}
			} else if (temp.getClass().toString().contains("ListBox")) {
				ListBox listBox = (ListBox) temp;
				if (!validate(listBox)) {
					result = false;
					setErrorFor(listBox);
					listBox.setFocus(true);
				}
			} else if (temp.getClass().toString().contains("TextBox")) {
				TextBox txtBox = (TextBox) temp;
				if (!validate(txtBox)) {
					result = false;
					setErrorFor(txtBox);
					txtBox.setFocus(true);
				}
			}
		}
//
//		if(result) {
//			if(isSuggestBoxValid(suggestBoxCityState)) {
//				clearError(suggestBoxCityState);
//			} else {
//				setErrorFor(suggestBoxCityState);
//				result = false;
//				suggestBoxCityState.setFocus(true);
//			}
//		}
//		
		if (result) {
			String date = comboBoxDateOfBirthDay.getItemText(comboBoxDateOfBirthDay.getSelectedIndex());
			String month = comboBoxDateOfBirthMonth.getItemText(comboBoxDateOfBirthMonth.getSelectedIndex());
			String year = comboBoxDateOfBirthYear.getItemText(comboBoxDateOfBirthYear.getSelectedIndex());

			result = AppClientUtils
					.isValidDate(Integer.parseInt(year), Integer.parseInt(month), Integer.parseInt(date));
			if (!result) {
				result = false;

				setErrorFor(comboBoxDateOfBirthDay);
				setErrorFor(comboBoxDateOfBirthMonth);
				setErrorFor(comboBoxDateOfBirthYear);

				comboBoxDateOfBirthDay.setFocus(true);

			} else {
				clearError(comboBoxDateOfBirthDay);
				clearError(comboBoxDateOfBirthMonth);
				clearError(comboBoxDateOfBirthYear);
			}
		}
		return result;
	}
	
	private boolean isSuggestBoxValid(SuggestBox suggestBox) {
		String str = suggestBox.getTextBox().getText().trim();
		if(str != null){
			CityDTO cityDTO = DataCache.getCityDTO(str);
			if(cityDTO != null) {
				return true;
			}
			else {
				return false;
			}
		} else {
			return false;
		}
	}

	private void setDuplicateUserNameErrorFor(final TextBox txtBox) {

		txtBox.getElement().getStyle().setProperty("border", "1px solid red");
		FlexTable ftError = (FlexTable) txtBox.getElement().getPropertyObject("duplicateUserName");
		ftError.setVisible(true);
		FlexTable parent = (FlexTable) txtBox.getParent();
		parent.setWidget(0, 1, ftError);
	}
	private void clearDuplicateUserNameError(TextBox txtBox) {
		FlexTable ftError = (FlexTable) txtBox.getElement().getPropertyObject("duplicateUserName");
		ftError.removeFromParent();
		txtBox.getElement().getStyle().clearBorderColor();
	}
	
	private void setErrorFor(final TextBox txtBox) {

		txtBox.getElement().getStyle().setProperty("border", "1px solid red");
		FlexTable ftError = (FlexTable) txtBox.getElement().getPropertyObject("errorBox");
		ftError.setVisible(true);
		FlexTable parent = (FlexTable) txtBox.getParent();
		parent.setWidget(0, 1, ftError);

		txtBox.addBlurHandler(new BlurHandler() {

			@Override
			public void onBlur(BlurEvent event) {
				if (txtBox.getElement().getId().equalsIgnoreCase("passwordTextBoxConfirmPassword")) {
					if (!passwordBoxConfirmPassword.getText().trim().equals(passwordBoxPassword.getText().trim())) {
						setErrorFor(txtBox);
					} else {
						clearError(txtBox);
					}
				} else {
					if (validate(txtBox)) {
						clearError(txtBox);
					} else {
						setErrorFor(txtBox);
					}
				}
			}
		});
	}
	
	private void setErrorFor(final SuggestBox suggestBox) {

		suggestBox.getElement().getStyle().setProperty("border", "1px solid red");
		FlexTable ftError = (FlexTable) suggestBox.getElement().getPropertyObject("errorBox");
		ftError.setVisible(true);
		FlexTable parent = (FlexTable) suggestBox.getParent();
		parent.setWidget(0, 1, ftError);

		suggestBox.getTextBox().addBlurHandler(new BlurHandler() {

			@Override
			public void onBlur(BlurEvent event) {
				if(isSuggestBoxValid(suggestBox)) {
					clearError(suggestBox);
				} else {
					setErrorFor(suggestBox);
				}
			}
		});
	}

	private void clearError(SuggestBox suggestBox) {
		FlexTable ftError = (FlexTable) suggestBox.getElement().getPropertyObject("errorBox");
		ftError.removeFromParent();
		suggestBox.getElement().getStyle().clearBorderColor();
	}

	private void clearError(TextBox txtBox) {
		FlexTable ftError = (FlexTable) txtBox.getElement().getPropertyObject("errorBox");
		ftError.removeFromParent();
		txtBox.getElement().getStyle().clearBorderColor();
	}

	private boolean validate(TextBox txtBox) {
		String strRegEx = txtBox.getElement().getAttribute("regEx");
		String strVal = txtBox.getText().trim();
		if (txtBox.getElement().getAttribute("required").equalsIgnoreCase("false")) {
			if (strVal.trim().isEmpty())
				return true;
			else
				return checkRegEx(strVal, strRegEx);
		} else {
			return checkRequired(strVal, strRegEx);
		}
	}

	private boolean checkRequired(String strVal, String strRegEx) {
		if (strVal.trim().isEmpty()) {
			return false;
		} else {
			return checkRegEx(strVal, strRegEx);
		}
	}

	private boolean checkRegEx(String strVal, String strRegEx) {
		return strVal.matches(strRegEx);
	}

	private boolean validate(ListBox listBox) {
		
		if (listBox.getSelectedIndex() > 0) {
			return true;
		}

		return false;
	}

	private void setErrorFor(final ListBox listBox) {

		listBox.setStyleName("gwt-ListBox-error");
		FlexTable ftError = (FlexTable) listBox.getElement().getPropertyObject("errorBox");
		ftError.setVisible(true);

		listBox.addChangeHandler(new ChangeHandler() {
			
			@Override
			public void onChange(ChangeEvent event) {
				if (validate(listBox)) {
					clearError(listBox);
				} else {
					setErrorFor(listBox);
				}
				
			}
		});
		
		listBox.addFocusHandler(new FocusHandler() {

			@Override
			public void onFocus(FocusEvent event) {
				if (validate(listBox)) {
					clearError(listBox);
				} else {
					setErrorFor(listBox);
				}
			}
		});
	}

	private void clearError(ListBox listBox) {
		
		FlexTable ftError = (FlexTable) listBox.getElement().getPropertyObject("errorBox");
		ftError.setVisible(false);
		listBox.setStyleName("gwt-ListBox");
		
	}

	public ArrayList<FocusWidget> getFormValidationWidgets() {

		if (formValidationWidgets == null) {
			formValidationWidgets = new ArrayList<FocusWidget>();

			formValidationWidgets.add(textBoxFirstName);
			formValidationWidgets.add(textBoxMiddleName);
			formValidationWidgets.add(textBoxLastName);
			formValidationWidgets.add(comboBoxDateOfBirthDay);
			formValidationWidgets.add(comboBoxDateOfBirthMonth);
			formValidationWidgets.add(comboBoxDateOfBirthYear);

			formValidationWidgets.add(textBoxAddressLine1);
			formValidationWidgets.add(textBoxAddressLine2);
			formValidationWidgets.add(textBoxPinCode);
			formValidationWidgets.add(textBoxPrimaryPhone);
			formValidationWidgets.add(textBoxSecondaryPhone);
			formValidationWidgets.add(textBoxPrimaryEmail);
			formValidationWidgets.add(textBoxSecondaryEmail);

			formValidationWidgets.add(textBoxUserName);
			formValidationWidgets.add(listBoxUserType);
			formValidationWidgets.add(passwordBoxPassword);
			formValidationWidgets.add(passwordBoxConfirmPassword);
			formValidationWidgets.add(listBoxSecurityQuestion);
			formValidationWidgets.add(textBoxSecurityAnswer);
			formValidationWidgets.add(textBoxHintForSecurityAnswer);
		}

		return formValidationWidgets;
	}

	private UserDTO getUserDTO() {
		UserDTO userDTO = new UserDTO();

		userDTO.setFirstName(textBoxFirstName.getText().trim());
		userDTO.setMiddleName(textBoxMiddleName.getText().trim());
		userDTO.setLastName(textBoxLastName.getText().trim());

		String date = comboBoxDateOfBirthDay.getItemText(comboBoxDateOfBirthDay.getSelectedIndex());
		String month = comboBoxDateOfBirthMonth.getItemText(comboBoxDateOfBirthMonth.getSelectedIndex());
		String year = comboBoxDateOfBirthYear.getItemText(comboBoxDateOfBirthYear.getSelectedIndex());

		userDTO.setDob(AppClientUtils.getDate(Integer.parseInt(year), Integer.parseInt(month), Integer.parseInt(date)));

		userDTO.setAddressLine1(textBoxAddressLine1.getText().trim());
		userDTO.setAddressLine2(textBoxAddressLine2.getText().trim());
		userDTO.setCity(DataCache.getCityDTO(suggestBoxCityState.getTextBox().getText().trim()));

		userDTO.setPinCode(Long.parseLong(textBoxPinCode.getText().trim()));
		userDTO.setPrimaryMobile(Long.parseLong(textBoxPrimaryPhone.getText().trim()));
		if (!textBoxSecondaryPhone.getText().trim().isEmpty())
			userDTO.setSecondaryMobile(Long.parseLong(textBoxSecondaryPhone.getText().trim()));
		userDTO.setPrimaryEmail(textBoxPrimaryEmail.getText().trim());
		userDTO.setSecondaryEmail(textBoxSecondaryEmail.getText().trim());

		userDTO.setUserName(textBoxUserName.getText().trim());
		userDTO.setUserTypeDTO(mapUserTypes.get(String.valueOf(listBoxUserType.getValue(listBoxUserType.getSelectedIndex()))));
		userDTO.setPassword(passwordBoxPassword.getText().trim());
		userDTO.setSecurityQuestion(listBoxSecurityQuestion.getItemText(listBoxSecurityQuestion.getSelectedIndex()));
		userDTO.setSecurityAnswer(textBoxSecurityAnswer.getText().trim());
		userDTO.setSecurityAnswerHint(textBoxHintForSecurityAnswer.getText().trim());

		userDTO.setLocked(false);
		userDTO.setActive(true);
		return userDTO;
	}

	private void enterFakeData() {
		
		textBoxFirstName.setText("FirstName");
		textBoxMiddleName.setText("MiddleName");
		textBoxLastName.setText("LastName");
		comboBoxDateOfBirthDay.setSelectedIndex(2);
		comboBoxDateOfBirthMonth.setSelectedIndex(2);
		comboBoxDateOfBirthYear.setSelectedIndex(2);

		textBoxAddressLine1.setText("AddressLine1");
		textBoxAddressLine2.setText("AddressLine2");
		suggestBoxCityState.getTextBox().setText("");
		textBoxPinCode.setText("413004");
		textBoxPrimaryPhone.setText("9881997788");
		textBoxSecondaryPhone.setText("");
		textBoxPrimaryEmail.setText("Jayashri@abc.xom");
		textBoxSecondaryEmail.setText("");

		textBoxUserName.setText("Jayashri85");
		listBoxUserType.setSelectedIndex(1);
		passwordBoxPassword.setText("M@trix5");
		passwordBoxConfirmPassword.setText("M@trix5");
		listBoxSecurityQuestion.setSelectedIndex(2);
		textBoxSecurityAnswer.setText("Jayashri");
		textBoxHintForSecurityAnswer.setText("Jayashri");

	}
	
}
